home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / bibtex / bibtex.ch < prev    next >
Text File  |  1989-03-08  |  17KB  |  602 lines

  1. % Change file for BibTeX for Berkeley UNIX, by H. Trickey
  2. % History:
  3. % 5/28/84    Initial implementation, version 0.41 of BibTeX
  4. % 7/1/84    Version 0.41a of BibTeX.
  5. % 12/17/84    Version 0.97c of BibTeX.
  6. % 2/12/85    Version 0.98c of BibTeX.
  7. % 2/25/85    Newer Version 0.98c of BibTeX
  8. % 3/25/85    Version 0.98f of BibTeX
  9. % 5/23/85    Version 0.98i of BibTeX
  10. % 2/11/88       Version 0.99b of BibTeX
  11. % 4/ 4/88    Version 0.99c; converted for use with web2c (ETM).
  12. % 8/ 3/88    Separated BIBPATH from TEXINPUTS in input file searching
  13.  
  14. @x banner
  15. @d banner=='This is BibTeX, Version 0.99c' {printed when the program starts}
  16. @y
  17. @d banner=='This is BibTeX, C Version 0.99c' {printed when the program starts}
  18. @z
  19.  
  20. @x terminal
  21. @d term_out == tty
  22. @d term_in == tty
  23. @y
  24. @d term_out == stdout
  25. @d term_in == stdin
  26. @z
  27.  
  28. @x debug..gubed, stat..tats, trace..ecart
  29. @d debug == @{        { remove the `|@{|' when debugging }
  30. @d gubed == @t@>@}    { remove the `|@}|' when debugging }
  31. @f debug == begin
  32. @f gubed == end
  33. @#
  34. @d stat == @{        { remove the `|@{|' when keeping statistics }
  35. @d tats == @t@>@}    { remove the `|@}|' when keeping statistics }
  36. @f stat == begin
  37. @f tats == end
  38. @#
  39. @d trace == @{        { remove the `|@{|' when in |trace| mode }
  40. @d ecart == @t@>@}    { remove the `|@}|' when in |trace| mode }
  41. @f trace == begin
  42. @f ecart == end
  43. @y
  44. @d debug == ifdef('DEBUG')
  45. @d gubed == endif('DEBUG')
  46. @f debug == begin
  47. @f gubed == end
  48. @#
  49. @d stat == ifdef('STAT')
  50. @d tats == endif('STAT')
  51. @f stat==begin
  52. @f tats==end
  53. @#
  54. @d trace == ifdef@&('TRACE')
  55. @d ecart == endif@&('TRACE')
  56. @f trace == begin
  57. @f ecart == end
  58. @z
  59.  
  60. @x
  61. @d incr(#) == #:=#+1    {increase a variable by unity}
  62. @d decr(#) == #:=#-1    {decrease a variable by unity}
  63. @y
  64. {These are defined as C macros}
  65. @z
  66.  
  67. @x compiler directives
  68. @{@&$C-,A+,D-@}     {no range check, catch arithmetic overflow, no debug overhead}
  69. @!debug @{@&$C+,D+@}@+ gubed        {but turn everything on when debugging}
  70. @y
  71. {Don't need 'em for C}
  72. @z
  73.  
  74. @x
  75.     goto exit_program;
  76. @y
  77.     uexit(0);
  78. @z
  79.  
  80. @x increase buf_size
  81. @!buf_size=1000; {maximum number of characters in an input line (or string)}
  82. @y
  83. @!buf_size=3000; {maximum number of characters in an input line (or string)}
  84. @z
  85.  
  86. @x increase pool_size
  87. @!pool_size=65000; {maximum number of characters in strings}
  88. @y
  89. @!pool_size=120000; {maximum number of characters in strings}
  90. @z
  91.  
  92. @x increase file_name_size
  93. @d file_name_size=40    {file names shouldn't be longer than this}
  94. @y
  95. @d file_name_size=1024    {file names shouldn't be longer than this}
  96. @z
  97.  
  98. @x declare real_name_of_file
  99. Most of what we need to do with respect to input and output can be handled
  100. by the I/O facilities that are standard in \PASCAL, i.e., the routines
  101. called |get|, |put|, |eof|, and so on. But
  102. standard \PASCAL\ does not allow file variables to be associated with file
  103. names that are determined at run time, so it cannot be used to implement
  104. \BibTeX; some sort of extension to \PASCAL's ordinary |reset| and |rewrite|
  105. is crucial for our purposes. We shall assume that |name_of_file| is a variable
  106. of an appropriate type such that the \PASCAL\ run-time system being used to
  107. implement \BibTeX\ can open a file whose external name is specified by
  108. |name_of_file|. \BibTeX\ does no case conversion for file names.
  109.  
  110. @<Globals in the outer block@>=
  111. @!name_of_file:packed array[1..file_name_size] of char;
  112.              {on some systems this is a \&{record} variable}
  113. @y
  114. Most of what we need to do with respect to input and output can be handled
  115. by the I/O facilities that are standard in \PASCAL, i.e., the routines
  116. called |get|, |put|, |eof|, and so on. But
  117. standard \PASCAL\ does not allow file variables to be associated with file
  118. names that are determined at run time, so it cannot be used to implement
  119. \BibTeX; some sort of extension to \PASCAL's ordinary |reset| and |rewrite|
  120. is crucial for our purposes. We shall assume that |name_of_file| is a variable
  121. of an appropriate type such that the \PASCAL\ run-time system being used to
  122. implement \BibTeX\ can open a file whose external name is specified by
  123. |name_of_file|. \BibTeX\ does no case conversion for file names.
  124.  
  125. The C version of BibTeX uses search paths to look for files to open.
  126. We use |real_name_of_file| to hold the |name_of_file| with a directory name
  127. from the path in front of it.
  128.  
  129. @<Globals in the outer block@>=
  130. @!name_of_file,@!real_name_of_file:packed array[1..file_name_size] of char;
  131. @z
  132.  
  133. @x opening files
  134. The \ph\ compiler with which the present version of \TeX\ was prepared has
  135. extended the rules of \PASCAL\ in a very convenient way. To open file~|f|,
  136. we can write
  137. $$\vbox{\halign{#\hfil\qquad&#\hfil\cr
  138. |reset(f,@t\\{name}@>,'/O')|&for input;\cr
  139. |rewrite(f,@t\\{name}@>,'/O')|&for output.\cr}}$$
  140. The `\\{name}' parameter, which is of type `\ignorespaces|packed
  141. array[@t\<\\{any}>@>] of text_char|', stands for the name of
  142. the external file that is being opened for input or output.
  143. Blank spaces that might appear in \\{name} are ignored.
  144.  
  145. The `\.{/O}' parameter tells the operating system not to issue its own
  146. error messages if something goes wrong. If a file of the specified name
  147. cannot be found, or if such a file cannot be opened for some other reason
  148. (e.g., someone may already be trying to write the same file), we will have
  149. |@!erstat(f)<>0| after an unsuccessful |reset| or |rewrite|.  This allows
  150. \TeX\ to undertake appropriate corrective action.
  151.  
  152. \TeX's file-opening procedures return |false| if no file identified by
  153. |name_of_file| could be opened.
  154.  
  155. @d reset_OK(#)==erstat(#)=0
  156. @d rewrite_OK(#)==erstat(#)=0
  157.  
  158. @<Procedures and functions for file-system interacting@>=
  159. function erstat(var f:file):integer; extern;    {in the runtime library}
  160. @#@t\2@>
  161. function a_open_in(var f:alpha_file):boolean;    {open a text file for input}
  162. begin reset(f,name_of_file,'/O'); a_open_in:=reset_OK(f);
  163. end;
  164. @#
  165. function a_open_out(var f:alpha_file):boolean;    {open a text file for output}
  166. begin rewrite(f,name_of_file,'/O'); a_open_out:=rewrite_OK(f);
  167. end;
  168. @y
  169. @ The \ph\ compiler with which the present version of \TeX\ was prepared has
  170. extended the rules of \PASCAL\ in a very convenient way for file opening.
  171. Berkeley {\mc UNIX} \PASCAL\ isn't nearly as nice as \ph.
  172. Normally, it bombs out if a file open fails.
  173. An external C procedure, |test_access| is used to check whether or not the
  174. open will work.  It is declared in the ``ext.h'' include file, and it returns
  175. |true| or |false|. The |name_of_file| global holds the file name whose access
  176. is to be tested.
  177. The first parameter for |test_access| is the access mode,
  178. one of |read_access_mode| or |write_access_mode|.
  179.  
  180. We also implement path searching in |test_access|:  its second parameter is
  181. one of the ``file path'' constants defined below.  If |name_of_file|
  182. doesn't start with |'/'| then |test_access| tries prepending pathnames
  183. from the appropriate path list until success or the end of path list
  184. is reached.
  185. On return, |real_name_of_file| contains the original name with the path
  186. that succeeded (if any) prepended.  It is the name used in the various
  187. open procedures.
  188.  
  189. Path searching is not done for output files.
  190.  
  191. @d read_access_mode=4  {``read'' mode for |test_access|}
  192. @d write_access_mode=2 {``write'' mode for |test_access|}
  193.  
  194. @d no_file_path=0    {no path searching should be done}
  195. @d input_file_path=1 {path specifier for input files}
  196. @d bib_file_path=2   {path specifier for .bib files}
  197.  
  198. @<Procedures and functions for file-system interacting@>=
  199. function a_open_in(var f:palpha_file; pathspec:integer):boolean;
  200.   {open a text file for input}
  201. var @!ok:boolean;
  202. begin
  203. if test_access(read_access_mode,pathspec) then
  204.     begin reset(f,real_name_of_file); ok:=true@+end
  205. else
  206.     ok:=false;
  207. a_open_in:=ok;
  208. end;
  209. @#
  210. function a_open_out(var f:palpha_file):boolean;
  211.   {open a text file for output}
  212. var @!ok:boolean;
  213. begin
  214. if test_access(write_access_mode,no_file_path) then
  215.     begin rewrite(f,real_name_of_file); ok:=true @+end
  216. else ok:=false;
  217. a_open_out:=ok;
  218. end;
  219. @z
  220.  
  221. @x
  222. @<Procedures and functions for file-system interacting@>=
  223. procedure a_close(var f:alpha_file);        {close a text file}
  224. begin close(f);
  225. end;
  226. @y
  227. {aclose will be defined as a C macro}
  228. @z
  229.  
  230. %%%%% overflow and confusion go here 
  231. @x faster input_ln
  232. Standard \PASCAL\ says that a file should have |eoln| immediately
  233. before |eof|, but \BibTeX\ needs only a weaker restriction: If |eof|
  234. occurs in the middle of a line, the system function |eoln| should return
  235. a |true| result (even though |f^| will be undefined).
  236.  
  237. @<Procedures and functions for all file I/O, error messages, and such@>=
  238. function input_ln(var f:alpha_file) : boolean;
  239.                 {inputs the next line or returns |false|}
  240. label loop_exit;
  241. begin
  242. last:=0;
  243. if (eof(f)) then input_ln:=false
  244. else
  245.   begin
  246.   while (not eoln(f)) do
  247.     begin
  248.     if (last >= buf_size) then
  249.     buffer_overflow;
  250.     buffer[last]:=xord[f^];
  251.     get(f); incr(last);
  252.     end;
  253.   get(f);
  254.   while (last > 0) do        {remove trailing |white_space|}
  255.     if (lex_class[buffer[last-1]] = white_space) then
  256.       decr(last)
  257.      else
  258.       goto loop_exit;
  259. loop_exit:
  260.   input_ln:=true;
  261.   end;
  262. end;
  263. @y
  264. With Berkeley {\mc UNIX} we call an external C procedure, |line_read|.
  265. That routine fills |buffer| from |0| onwards with the |xord|'ed values
  266. of the next line, setting |last| appropriately.  It will stop if
  267. |last=buf_size|, and the following will cause an ``overflow'' abort.
  268.  
  269. @<Procedures and functions for all file I/O, error messages, and such@>=
  270. function input_ln(var f:alpha_file) : boolean;
  271.   {inputs the next line or returns |false|}
  272. label loop_exit;
  273. begin
  274. last:=0;
  275. if eof(f) then input_ln:=false
  276. else
  277.   begin
  278.   line_read(f,buf_size);
  279.   if last>=buf_size then
  280.     overflow('buffer size ',buf_size);
  281.   while (last > 0) do        {remove trailing |white_space|}
  282.     if lex_class[buffer[last-1]] = white_space then
  283.       decr(last)
  284.      else
  285.       goto loop_exit;
  286. loop_exit:
  287.   input_ln:=true;
  288.   end;
  289. end;
  290. @z
  291.  
  292. @x
  293. if (length(file_name) > file_name_size) then
  294.     begin
  295.     print ('File=');
  296.     print_pool_str (file_name);
  297.     print_ln (',');
  298.     file_nm_size_overflow;
  299.     end;
  300. name_ptr := 1;
  301. @y
  302. if (length(file_name) > file_name_size) then
  303.     begin
  304.     print ('File=');
  305.     print_pool_str (file_name);
  306.     print_ln (',');
  307.     file_nm_size_overflow;
  308.     end;
  309. name_ptr := 0;
  310. @z
  311.  
  312. @x
  313. name_ptr := name_length + 1;
  314. p_ptr := str_start[ext];
  315. while (p_ptr < str_start[ext+1]) do
  316.     begin
  317.     name_of_file[name_ptr] := chr (str_pool[p_ptr]);
  318.     incr(name_ptr); incr(p_ptr);
  319.     end;
  320. name_length := name_length + length(ext);
  321. name_ptr := name_length+1;
  322. while (name_ptr <= file_name_size) do    {pad with blanks}
  323.     begin
  324.     name_of_file[name_ptr] := ' ';
  325.     incr(name_ptr);
  326.     end;
  327. @y
  328. name_ptr := name_length;
  329. p_ptr := str_start[ext];
  330. while (p_ptr < str_start[ext+1]) do
  331.     begin
  332.     name_of_file[name_ptr] := chr (str_pool[p_ptr]);
  333.     incr(name_ptr); incr(p_ptr);
  334.     end;
  335. name_length := name_length + length(ext);
  336. name_of_file[name_length] := ' ';
  337. @z
  338.  
  339. @x
  340.     print_pool_str (area); print (name_of_file,',');
  341.     file_nm_size_overflow;
  342.     end;
  343. name_ptr := name_length;
  344. while (name_ptr > 0) do        {shift up name}
  345.     begin
  346.     name_of_file[name_ptr+length(area)] := name_of_file[name_ptr];
  347.     decr(name_ptr);
  348.     end;
  349. name_ptr := 1;
  350. p_ptr := str_start[area];
  351. while (p_ptr < str_start[area+1]) do
  352. @y
  353.     print_pool_str (area); print_str (name_of_file,',');
  354.     file_nm_size_overflow;
  355.     end;
  356. name_ptr := name_length;
  357. while (name_ptr > 0) do        {shift up name}
  358.     begin
  359.     name_of_file[name_ptr+length(area)] := name_of_file[name_ptr];
  360.     decr(name_ptr);
  361.     end;
  362. name_ptr := 0;
  363. p_ptr := str_start[area];
  364. while (p_ptr < str_start[area+1]) do
  365. @z
  366.  
  367. @x
  368. for i:=1 to len do
  369.     buffer[i] := xord[pds[i]];
  370. @y
  371. for i:=1 to len do
  372.     buffer[i] := xord[pds[i-1]];
  373. @z
  374.  
  375. @x
  376. procedure sam_too_long_file_name_print;
  377. begin
  378. write (term_out,'File name `');
  379. name_ptr := 1;
  380. while (name_ptr <= aux_name_length) do
  381.     begin
  382.     write (term_out,name_of_file[name_ptr]);
  383. @y
  384. procedure sam_too_long_file_name_print;
  385. begin
  386. write (term_out,'File name `');
  387. name_ptr := 0;
  388. while (name_ptr < aux_name_length) do
  389.     begin
  390.     write (term_out,name_of_file[name_ptr]);
  391. @z
  392.  
  393. @x
  394. procedure sam_wrong_file_name_print;
  395. begin
  396. write (term_out,'I couldn''t open file name `');
  397. name_ptr := 1;
  398. while (name_ptr <= name_length) do
  399.     begin
  400.     write (term_out,name_of_file[name_ptr]);
  401.     incr(name_ptr);
  402.     end;
  403. write_ln (term_out,'''');
  404. end;
  405. @y
  406. procedure sam_wrong_file_name_print;
  407. begin
  408. write (term_out,'I couldn''t open file name `');
  409. name_ptr := 0;
  410. while (name_ptr < name_length) do
  411.     begin
  412.     write (term_out,name_of_file[name_ptr]);
  413.     incr(name_ptr);
  414.     end;
  415. write_ln (term_out,'''');
  416. end;
  417. @z
  418.  
  419. @x reading the command line
  420. This procedure consists of a loop that reads and processes a (nonnull)
  421. \.{.aux} file name.  It's this module and the next two that must be
  422. changed on those systems using command-line arguments.  Note: The
  423. |term_out| and |term_in| files are system dependent.
  424.  
  425. @<Procedures and functions for the reading and processing of input files@>=
  426. procedure get_the_top_level_aux_file_name;
  427. label aux_found,@!aux_not_found;
  428. var @<Variables for possible command-line processing@>@/
  429. begin
  430. check_cmnd_line := false;            {many systems will change this}
  431. loop
  432.     begin
  433.     if (check_cmnd_line) then
  434.     @<Process a possible command line@>
  435.       else
  436.     begin
  437.     write (term_out,'Please type input file name (no extension)--');
  438.     if (eoln(term_in)) then            {so the first |read| works}
  439.         read_ln (term_in);
  440.     aux_name_length := 0;
  441.     while (not eoln(term_in)) do
  442.         begin
  443.         if (aux_name_length = file_name_size) then
  444.         begin
  445.         while (not eoln(term_in)) do    {discard the rest of the line}
  446.             get(term_in);
  447.         sam_you_made_the_file_name_too_long;
  448.         end;
  449.         incr(aux_name_length);
  450.         name_of_file[aux_name_length] := term_in^;
  451.         get(term_in);
  452.         end;
  453.     end;
  454.     @<Handle this \.{.aux} name@>;
  455. aux_not_found:
  456.     check_cmnd_line := false;
  457.     end;
  458. aux_found:            {now we're ready to read the \.{.aux} file}
  459. end;
  460. @y
  461. @<Procedures and functions for the reading and processing of input files@>=
  462. procedure get_the_top_level_aux_file_name;
  463. label aux_found,@!aux_not_found;
  464. begin
  465. loop
  466.     begin
  467.     if (gargc > 1) then
  468.     @<Process a possible command line@>
  469.       else begin
  470.     write (term_out,'Please type input file name (no extension)--');
  471.     aux_name_length := 0;
  472.     while (not eoln(term_in)) do begin
  473.         if (aux_name_length = file_name_size) then begin
  474.         readln(term_in);
  475.         sam_you_made_the_file_name_too_long;
  476.         end;
  477.         name_of_file[aux_name_length] := getc(term_in);
  478.         incr(aux_name_length);
  479.     end;
  480.     if (eof(term_in)) then begin
  481.         writeln(term_out);
  482.         writeln(term_out,'Unexpected end of file on terminal---giving up!');
  483.         uexit(1);
  484.     end;
  485.     readln(term_in);
  486.       end;
  487.     @<Handle this \.{.aux} name@>;
  488. aux_not_found:
  489.     gargc := 0;
  490.     end;
  491. aux_found:            {now we're ready to read the \.{.aux} file}
  492. end;
  493. @z
  494.  
  495. @x
  496. @<Variables for possible command-line processing@>=
  497. @!check_cmnd_line : boolean;    {|true| if we're to check the command line}
  498. @y
  499. @z
  500.  
  501. @x
  502. @<Process a possible command line@>=
  503. begin
  504. do_nothing;        {the ``default system'' doesn't use the command line}
  505. end
  506. @y
  507. @<Process a possible command line@>=
  508. aux_name_length := get_cmd_line(name_of_file, file_name_size)
  509. @z
  510.  
  511. @x
  512. if (not a_open_in(cur_aux_file)) then
  513.     sam_you_made_the_file_name_wrong;
  514. @y
  515. if (not a_open_in(cur_aux_file,no_file_path)) then
  516.     sam_you_made_the_file_name_wrong;
  517. @z
  518.  
  519. @x
  520. while (name_ptr <= name_length) do
  521.     begin
  522.     buffer[name_ptr] := xord[name_of_file[name_ptr]];
  523.     incr(name_ptr);
  524.     end;
  525. @y
  526. while (name_ptr <= name_length) do
  527.     begin
  528.     buffer[name_ptr] := xord[name_of_file[name_ptr-1]];
  529.     incr(name_ptr);
  530.     end;
  531. @z
  532.  
  533. % Handle path searching on opening files
  534. @x
  535. if (not a_open_in(cur_bib_file)) then
  536.     begin
  537.     add_area (s_bib_area);
  538.     if (not a_open_in(cur_bib_file)) then
  539.     open_bibdata_aux_err ('I couldn''t open database file ');
  540.     end;
  541. @y
  542. if (not a_open_in(cur_bib_file,bib_file_path)) then
  543.     open_bibdata_aux_err ('I couldn''t open database file ');
  544. @z
  545.  
  546. @x
  547. add_extension (s_bst_extension);
  548. if (not a_open_in(bst_file)) then
  549.     begin
  550.     add_area (s_bst_area);
  551.     if (not a_open_in(bst_file)) then
  552.     begin
  553.     print ('I couldn''t open style file ');
  554.     print_bst_name;@/
  555.     bst_str := 0;                {mark as unused again}
  556.     aux_err_return;
  557.     end;
  558.     end;
  559. @y
  560. add_extension (s_bst_extension);
  561. if (not a_open_in(bst_file,input_file_path)) then
  562.     begin
  563.     print ('I couldn''t open style file ');
  564.     print_bst_name;@/
  565.     bst_str := 0;                {mark as unused again}
  566.     aux_err_return;
  567.     end;
  568. @z
  569.  
  570. @x
  571. name_ptr := name_length+1;
  572. @y
  573. name_ptr := name_length;
  574. @z
  575.  
  576. % More search path stuff
  577. @x
  578. if (not a_open_in(cur_aux_file)) then
  579. @y
  580. if (not a_open_in(cur_aux_file, no_file_path)) then
  581. @z
  582.  
  583. @x
  584. buf_ptr2 := last;    {to get the first input line}
  585. loop
  586.     begin
  587.     if (not eat_bst_white_space) then    {the end of the \.{.bst} file}
  588.     goto bst_done;
  589.     get_bst_command_and_process;
  590.     end;
  591. bst_done: a_close (bst_file);
  592. @y
  593. buf_ptr2 := last;    {to get the first input line}
  594. hack1;
  595.     begin
  596.     if (not eat_bst_white_space) then    {the end of the \.{.bst} file}
  597.     hack2;
  598.     get_bst_command_and_process;
  599.     end;
  600. bst_done: a_close (bst_file);
  601. @z
  602.